iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Software Development

Rust Web API 從零開始系列 第 14

Day14 - 幫API加上OpenAPI文件吧

  • 分享至 

  • xImage
  •  

Restful API的開發者應該都熟悉,我們會撰寫符合OpenAPI規格的文件以便於串接。在Rust中,除了poem這個框架原生支持OpenAPI開發外,其他框架則可以通過utoipa這個套件來協助生成OpenAPI文件。首先,為專案添加套件依賴:

cargo add utoipa --features "utoipa/axum_extras utoipa/uuid"

utoipa對於幾個常見的框架都有支援。如果需要使用UUID,則需要額外開啟特性。另外讓我們再安裝一個套件,幫站台加上Swagger UI:

cargo add utoipa-swagger-ui --features axum

接下來我們就要來開始撰寫文件了。

OpenApi Macros

先增加doc.rs用來放文件

use crate::handler::*;

use utoipa::OpenApi;

#[derive(OpenApi)]
#[openapi(
    paths(health_check, subscribe),
    components(schemas(NewSubscriber))
)]
pub struct ApiDoc;

我們要先建立一個結構用來操作OpenAPI,[derive(OpenApi)]讓套件可以透過這個結構生成文件。在utoipa中我們需要手動將handler與操作資源加入文件中,這邊可以注意一下因為restful api為資源導向的,所以在設計承接HTTP請求的物件時(components區塊),應該要思考這個物件對外呈現名稱的意義。

Path

接下來我們就直接把文件寫在handler上,以訂閱的API為例:

#[utoipa::path(
    post,
    path = "/subscriptions",
    tag = "subscription",
    request_body(
        content = NewSubscriber,
        content_type = "application/x-www-form-urlencoded"),
    responses(
        (status = 200),
        (status = 400)
    ))]
pub async fn subscribe(state: State<AppState>, Form(data): Form<NewSubscriber>) -> Result<StatusCode,StatusCode> {
    //// 省略內容
}

#[derive(Deserialize, Debug, ToSchema)]
pub struct NewSubscriber {
    /// Subscriber Email
    pub email: Option<String>,
    /// Subscriber Name
    pub name: Option<String>,
}

透過utoipa::path來撰寫API的規格,我們要注意他的HTTP Method,標示出路徑。關於request body可以直接參考使用的物件,最後要在NewSubscriber上加上ToSchema特性,並且用註解標示出屬性的名稱,這樣就可以順利的產出文件了。

Swagger UI

最後我們調整一下路由

//// application.rs
pub fn build() -> Router {
    let database = Database::connect("postgres://postgres:postgres@localhost:5432/marvinhsu_zero_to_production")
        .unwrap();
        
    let app = Router::new()
        .route("/", get(health_check))
        .route("/subscriptions", post(subscribe))
        /// 在路由中加入swagger
        .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
        .with_state(AppState {
            database
        });;
    app
}

因為前面已經透過#[derive(OpenApi)]對ApiDoc加工,utoipa自動幫它加上了openapi()方法。merge是Axum提供的方法,可以將多個路由結構合併,有利於將應用程式拆分成更小的模組。接下來運行程式應該就可以看到 Swagger UI了。

小結

在加上OpenAPI的過程中,對我來說最大的收穫其實是好好的讀了一下OpenAPI的規格,由於平常比較少直接撰寫文件(.Net自動生成太方便了),也因此不會注意到一些細節,比如說我們在看swagger的時候只會把焦點放在api的部份,但其實對於API溝通來說,schema的語意也非常重要。


上一篇
Day13 - 在Axum中共享資料
下一篇
Day15 - 管理應用程式的組態
系列文
Rust Web API 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言